#include "opencv_filter.h"

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;

void doOpencvFilter1()
{
	Mat img = imread("test.jpg");
	imshow("src", img);
	Mat out;
	boxFilter(img, out, -1, Size(5, 5));//-1指原图深度
	imshow("boxFilter", out);
	waitKey(0);
}



void doOpencvFilter2()
{
	Mat img = imread("test.jpg");
	imshow("src", img);
	Mat out;
	blur(img, out, Size(5, 5));//-1指原图深度
	imshow("blur", out);
	waitKey(0);

}


void doOpencvFilter3()
{
	Mat img = imread("test.jpg");
	imshow("src", img);
	Mat out;
	GaussianBlur(img, out, Size(3, 3), 0, 0);
	imshow("GaussianBlur", out);
	waitKey(0);

}


void doOpencvFilter4()
{
	Mat img = imread("test.jpg");
	imshow("src", img);
	Mat out;
	medianBlur(img, out, 7);//第三个参数表示孔径的线性尺寸，它的值必须是大于1的奇数
	imshow("medianBlur", out);
	waitKey(0);

}


void doOpencvFilter5()
{
	Mat img = imread("test.jpg");
	imshow("src", img);
	Mat out;
	bilateralFilter(img, out, 25, 25 * 2, 25 / 2);
	imshow("bilateralFilter", out);
	waitKey(0);

}

static int calculate_adaptive_threshold(const Mat& channel, float peak_ratio = 0.85) {
	// 步骤1：计算直方图
	const int histSize = 256;
	float range[] = { 0, 256 };
	const float* histRange = { range };
	Mat hist;
	calcHist(&channel, 1, 0, Mat(), hist, 1, &histSize, &histRange);

	// 步骤2：寻找主波峰位置
	Point max_loc;
	minMaxLoc(hist, 0, 0, 0, &max_loc);
	int main_peak = max_loc.y;

	// 步骤3：动态阈值计算策略
	int threshold_val = 128; // 默认值

	// 策略1：主波峰右侧下降85%的位置
	float peak_value = hist.at<float>(main_peak);
	for (int i = main_peak; i < histSize; ++i) {
		if (hist.at<float>(i) < peak_value * (1 - peak_ratio)) {
			threshold_val = i;
			break;
		}
	}

	// 策略2：验证阈值有效性（避免全黑/全白情况）
	if (threshold_val < 5 || threshold_val > 250) {
		threshold_val = 128; // 回退默认值
	}

	return threshold_val;
}

void doOpencvFilter6()
{
	Mat img = imread("t9.jpeg");
	imshow("src", img);

	//Mat gray;
	//cvtColor(img, gray, CV_RGB2GRAY);//灰度化
	//imshow("gray", img);

	Mat lab;
	cvtColor(img, lab, COLOR_BGR2Lab);

	vector<Mat> lab_channels;
	split(lab, lab_channels);
	imshow("1", lab_channels[0]);
	imshow("2", lab_channels[1]);
	//imshow("3", lab_channels[2]);

	Mat l_channel = lab_channels[0];  // 亮度通道
	Mat a_channel = lab_channels[1]; // 色度A通道（红绿轴）
	
	Mat shadow_mask_l, shadow_mask_a, final_mask;
	adaptiveThreshold(l_channel, shadow_mask_l, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 201, 30);
	imshow("shadow_mask_l", shadow_mask_l);

	// 动态计算色度阈值
	int adaptive_thresh = calculate_adaptive_threshold(a_channel, 0.95);
	threshold(a_channel, shadow_mask_a, adaptive_thresh, 255, THRESH_BINARY_INV);
	imshow("shadow_mask_a", shadow_mask_a);

	bitwise_and(shadow_mask_l, shadow_mask_a, final_mask);
	imshow("final_mask1", final_mask);
	
	Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(7, 7));  // 扩大核尺寸
	morphologyEx(final_mask, final_mask, MORPH_CLOSE, kernel, Point(-1, -1), 1);
	//imshow("final_mask2", final_mask);

	vector<vector<Point>> contours;
	findContours(final_mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	for (auto& cnt : contours) {
		if (contourArea(cnt) > 500) {  // 过滤小面积噪声
			drawContours(final_mask, vector<vector<Point>>{cnt}, -1, Scalar(0), FILLED);
		}
	}

	//imshow("final_mask3", final_mask);
	
	waitKey(0);
}